/*
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * Portions created by the Initial Developer are
 * Copyright (C) 2012 the Initial Developer.
 * All Rights Reserved.
 *
 * The Original Code is this.
 *
 * The Initial Developer of the Original Code is the author below.
 */
/**
 * @file Semaphore.cpp
 * @brief auto generated.
 * @author K.Ozaki
 * @date 2011/03/11
 */

#include "semi/posix/Semaphore.h"

namespace semi {

namespace posix {

Semaphore::Semaphore() {
    this->id = 0;
}

Semaphore::Semaphore(std::string nm) {
    this->init(nm);
}

Semaphore::~Semaphore() {
    this->close();
}
void Semaphore::init(std::string nm) {

    this->id = 0;
    this->name = semi::util::StringUtil::replace(nm, "/", "");
    this->name = semi::util::StringUtil::replace(this->name, ".", "");
    this->name = "/." + this->name;

    //    std::cout << "    Semaphore::init " << this->id << " " << this->name
    //            << std::endl;
}

bool Semaphore::open() {

    if (0 != this->id)
        return false;

    this->id = sem_open(this->name.c_str(), O_CREAT | O_RDWR,
            S_IRWXU | S_IRWXO, 1);

    //    std::cout << "    Semaphore::open end " << this->id << " " << this->name
    //            << std::endl;
    if (0 == id) {
        std::stringstream ss;
        ss << "Semaphore::open error sem_open " << name.c_str() << " id:" << id;
        perror(ss.str().c_str());
        return false;
    }
    return true;
}

bool Semaphore::close() {

    int ret = 0;
    if (0 != this->id)
        ret = sem_close(id);
    this->id = 0;
    return 0 == ret;
}

bool Semaphore::unlink() {

    this->close();
    int ret = sem_unlink(name.c_str());
    return 0 == ret;
}

bool Semaphore::wait() {

    this->open();

    if (0 == this->id)
        return false;

    int cnt = this->getvalue();
    cnt = cnt * -1 + 1;
    //    std::cout << "    Semaphore::wait count:" << cnt << " " << this->name
    //            << std::endl;

    int ret = sem_wait(this->id);

    return 0 == ret;
}

bool Semaphore::post() {

    this->open();

    if (0 == this->id)
        return false;

    int ret = 0;
    if (this->getvalue() < 1)
        ret = sem_post(this->id);
    return 0 == ret;
}

int Semaphore::getvalue() {

    this->open();
    if (0 == this->id)
        return -1;

    int cnt = -1;
    int ret = sem_getvalue(this->id, &cnt);

    //    std::cout << "@@@getvalue@@" << ret << std::endl;
    return cnt;
}

void Semaphore::postAll() {
    int cnt = this->getvalue();
    cnt = cnt * -1 + 1;
    for (int i = 0; i < cnt; i++)
        this->post();
    //    std::cout << "    Semaphore::postAll " << this->name << " count:" << cnt
    //            << std::endl;
}

void Semaphore::terminate() {
    std::cout << "    Semaphore::terminate start" << this->name << std::endl;
    this->postAll();
    this->close();
    this->unlink();
}

}
}
